package com.cmw.core.base.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cmw.core.base.exception.ServiceException;
import com.cmw.core.kit.ikexpression.FormulaUtil;
import com.cmw.core.util.StringHandler;

/**
 * 公式模型
 * @author chengmingwei
 * @date 2014-03-14
 */
@SuppressWarnings("serial")
public class FormulaModel implements Serializable{
	static Logger logger = Logger.getLogger(FormulaModel.class);
	//公式表达式
	private String exp;
	//公式参数
	private String pars;
	//编译好的参数列表
	private List<String[]> parsList = new ArrayList<String[]>();
	/**
	 * 获取公式表达式
	 * @return 公式表达式 
	 */
	public String getExp() {
		return exp;
	}
	
	/**
	 * 设置公式表达式
	 * @param exp 公式表达式 
	 */
	public void setExp(String exp) {
		this.exp = exp;
	}
	
	/**
	 * 获取公式参数
	 * @return 返回公式参数
	 */
	public String getPars() {
		return pars;
	}
	
	/**
	 * 设置公式参数
	 * @param pars
	 */
	public void setPars(String pars) {
		this.pars = pars;
	}
	
	/**
	 * 解析公式字符串
	 * @param formulaStr	公式字符串
	 * @throws ServiceException 
	 */
	public void parseFormulaStr(String formulaStr) throws ServiceException{
		if(!StringHandler.isValidStr(formulaStr)) throw new ServiceException("公式字符串参数不能为空!");
		String[] formulaArr = formulaStr.split("##");
		if(null == formulaArr || formulaArr.length == 0) throw new ServiceException("公式字符串参数不能为空!");
		this.exp = formulaArr[0];
		if(formulaArr.length == 1) return;
		this.pars = formulaArr[1];
		if(!StringHandler.isValidStr(this.pars)) return;
		String[] parsArr = this.pars.split(",");
		if(null == parsArr || parsArr.length == 0) return;
		for(String parsStr : parsArr){
			String[] piArr = parsStr.split(":");
			if(piArr.length < 2) throw new ServiceException("参数：["+parsStr+"]格式不对,必须是 \"参数名:数据类型\"这种格式!");
			parsList.add(piArr);
		}
	}
	
	/**
	 * 获取公式计算结果
	 * @param params
	 * @return
	 * @throws ServiceException
	 */
	public Object getResultByFormula(Map<String,Object> params) throws ServiceException{
		checkPars(params);
		fmtPars(params);
		Object result = FormulaUtil.parseExpression(this.exp, params);
		logger.info(this.exp+"公式结果："+result+"\n");
		return result;
	}
	
	/**
	 * 检查参数
	 * @param params
	 * @throws ServiceException
	 */
	private void checkPars(Map<String,Object> params) throws ServiceException{
		if(null == parsList|| parsList.size() == 0) return;
		if(null == params || params.size() == 0) throw new ServiceException("公式：["+this.exp+"]要求要提供以下参数："+this.pars+"!");
		for(String[] pars : parsList){
			String parsName = pars[0];
			String dataType = pars[1];
			if(!params.containsKey(parsName)) throw new ServiceException("在调用 getResultByFormula 方法时，必须提供\""+parsName+"\"参数!");
			try{
				Object objVal = params.get(parsName);
				if(!StringHandler.isValidObj(objVal)) throw new ServiceException("参数:"+parsName+"的值不能为空!");
				StringHandler.getValByType(objVal.toString(), dataType);
			}catch(Exception e){
				e.printStackTrace();
				throw new ServiceException(e);
			}
		
		}
	}
	
	private void fmtPars(Map<String,Object> params){
		for(String[] pars : parsList){
			String parsName = pars[0];
			String dataType = pars[1];
			Object objVal = params.get(parsName);
			objVal = StringHandler.getValByType(objVal.toString(), dataType);
			params.put(parsName, objVal);
		}
	}
}
